package com.ce.pms.system.custservice.service.impl;

import java.lang.reflect.Constructor;
import java.lang.reflect.ParameterizedType;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

import com.ce.common.util.BlankUtil;
import com.ce.pms.base.service.impl.PmsBaseServiceImpl;
import com.ce.pms.base.vo.SearchVO;
import com.ce.pms.exception.BusinessException;
import com.ce.util.BeanUtil;
import com.sitechasia.webx.core.model.IDomainObject;
import com.sitechasia.webx.core.model.IViewObject;
import com.sitechasia.webx.core.support.Page;
import com.sitechasia.webx.core.utils.base.PopulateUtil;

/**
 * 描述：客户事件的业务配置模块serivce抽象基类
 * @author 王浩羽
 *
 * @param <V> VO
 * @param <D> DO
 */
public abstract class AbstractCustomerEventServiceImpl<V extends IViewObject, D extends IDomainObject> extends PmsBaseServiceImpl
{
	/**
	 * 方法描述: DO -> VO
	 * @author: 王浩羽
	 * Create on: Dec 22, 2008
	 * @param sourceDO
	 * @param targetVO
	 * @return
	 * Edit author:
	 * Edit on:
	 * 修改原因:
	 */
	protected V assembleD2V(D sourceDO, V targetVO) {
		return assembleD2V(sourceDO, targetVO, null);
	}

	/**
	 * 方法描述:VO -> DO
	 * @author: 王浩羽
	 * Create on: Dec 22, 2008
	 * @param sourceVO
	 * @param targetDO
	 * @return
	 * Edit author:
	 * Edit on:
	 * 修改原因:
	 */
	protected D assembleV2D(V sourceVO, D targetDO) {
		D result = targetDO;
		if(result==null)
		{
			result = (D)newInstance(getDClassType());
		}
		BeanUtil.convertVoAsDo(sourceVO, result);
		return result;
	}

	/**
	 * 方法描述:拷贝数据
	 * @author: 王浩羽
	 * Create on: Dec 22, 2008
	 * @param source
	 * @param target
	 * @param ignoreProperties 忽略字段
	 * @return
	 * Edit author:
	 * Edit on:
	 * 修改原因:
	 */
	protected V assembleD2V(D source, V target,String[] ignoreProperties)
	{
		V result = target;
		if(result==null)
		{
			result = (V)newInstance(getVClassType());
		}
		PopulateUtil.populate(source, result, ignoreProperties);
		return result;
	}

	/**
	 * 方法描述:拷贝数据
	 * @author: 王浩羽
	 * Create on: Dec 22, 2008
	 * @param source
	 * @param target
	 * @param ignoreProperties 忽略字段
	 * @return
	 * Edit author:
	 * Edit on:
	 * 修改原因:
	 */
	protected D assembleV2D(V source, D target,String[] ignoreProperties)
	{
		D result = target;
		if(result==null)
		{
			result = (D)newInstance(getDClassType());
		}
		PopulateUtil.populate(source, result, ignoreProperties);
		return result;
	}

	/**
	 * 方法描述: 通过反射实现对象构造
	 * @author: 王浩羽
	 * Create on: Dec 22, 2008
	 * @param clazz
	 * @return
	 * Edit author:
	 * Edit on:
	 * 修改原因:
	 */
    private Object newInstance(Class clazz){
		try
		{
			Constructor cons = clazz.getConstructor(new Class[0]);
			return cons.newInstance(new Object[0]);
		}
		catch(Exception e)
		{
			e.printStackTrace();
		}
		return null;
    }

    /**
     * 方法描述: 获取泛型V的具体类型
     * @author: 王浩羽
     * Create on: Dec 22, 2008
     * @return
     * Edit author:
     * Edit on:
     * 修改原因:
     */
	protected Class<V> getVClassType()
	{
		 return (Class<V>) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0];
	}

	/**
	 * 方法描述:获取泛型D的具体类型
	 * @author: 王浩羽
	 * Create on: Dec 22, 2008
	 * @return
	 * Edit author:
	 * Edit on:
	 * 修改原因:
	 */
	protected Class<D> getDClassType()
	{
		 return (Class<D>) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[1];
	}

	/**
	 * 方法描述: DO列表转换称VO列表
	 * @author: 王浩羽
	 * Create on: Dec 22, 2008
	 * @param dOList
	 * @return
	 * Edit author:
	 * Edit on:
	 * 修改原因:
	 */
	protected List<V> assembleDOList2VOList(List<D> dOList){
		if(BlankUtil.isBlank(dOList))
		{
			return Collections.EMPTY_LIST;
		}
		List<V> vOList = new ArrayList<V>();
		for(D dO :dOList)
		{
			vOList.add(assembleD2V(dO, null));
		}
		return vOList;
	}

	/**
	 * 方法描述:根据ID查找VO
	 * @author: 王浩羽
	 * Create on: Dec 22, 2008
	 * @param id
	 * @return
	 * Edit author:
	 * Edit on:
	 * 修改原因:
	 */
	public V findObjectVOById(Long id){
		D objectDO = findObjectDOById(id);
		V objectVO = assembleD2V(objectDO, null);
		return objectVO;
	}

	/**
	 * 方法描述:根据ID查找DO
	 * @author: 王浩羽
	 * Create on: Dec 22, 2008
	 * @param id
	 * @return
	 * Edit author:
	 * Edit on:
	 * 修改原因:
	 */
	abstract protected D findObjectDOById(Long id);

	/**
	 * 方法描述: 按页查找VO列表
	 * @author: 王浩羽
	 * Create on: Dec 22, 2008
	 * @param searchVO
	 * @return
	 * Edit author:
	 * Edit on:
	 * 修改原因:
	 */
	@SuppressWarnings("unchecked")
	protected Page queryVOListByPage(SearchVO searchVO){
		searchVO.checkRule();
		Page returnPage = queryDOListByPage(searchVO);
		List<D> doList = returnPage.getResult();
		returnPage.setResult(assembleDOList2VOList(doList));
		return returnPage;
	}
	
	/**
	 * 方法描述: 按页查找DO列表
	 * @author: 王浩羽
	 * Create on: Dec 22, 2008
	 * @param searchVO
	 * @return
	 * Edit author:
	 * Edit on:
	 * 修改原因:
	 */
	abstract protected Page queryDOListByPage(SearchVO searchVO);

	/**
	    * 功能描述:  检查名称是否已经存在，存在则抛出异常<br>
	    * @param name
	    * Create author: 王浩羽 <br>
	    * Create on:Dec 25, 2008  <br>
	    * Edit author:  <br>
	    * Edit on:    <br>
	    * Why:     <br>
	    */
	public void checkExistenceByName(String name){
		if(isNameExisit(name)){
			throw new BusinessException(getNameExisitExceptionInoKey(),BusinessException.WARNING);
		}
	}
	/**
	 * 功能描述:  检查是否存在名字<br>
	 * @param name
	 * @return
	 * Create author: 王浩羽 <br>
	 * Create on:Dec 25, 2008  <br>
	 * Edit author:  <br>
	 * Edit on:    <br>
	 * Why:     <br>
	 */
	abstract protected boolean isNameExisit(String name);

	/**
	 * 功能描述: 获取名称已存在时抛出异常的信息所对应的key <br>
	 * @return
	 * Create author: 王浩羽 <br>
	 * Create on:Dec 29, 2008  <br>
	 * Edit author:  <br>
	 * Edit on:    <br>
	 * Why:     <br>
	 */
	abstract protected String getNameExisitExceptionInoKey();
	
	/**
	 *   用于DO对象排序<br>
	 *   用法：Collections.sort(dOList, new DOComparator());
	 * 	 * @author 王浩羽
	 *
	 */
	public class DOComparator implements Comparator<D>{
		public int compare(D o1, D o2)
		{
			return compareDO(o1,o2);
		}
	}
	
	/**
	 * 功能描述: 排序  <br>
	 * @param list
	 * Create author: 王浩羽 <br>
	 * Create on:Jan 19, 2009  <br>
	 * Edit author:  <br>
	 * Edit on:    <br>
	 * Why:     <br>
	 */
	protected void sortList(List<D> list){
		if(list==null || list.isEmpty())
		{
			return;
		}
		Collections.sort(list, new DOComparator());
	}
	/**
	 * 功能描述: 自定义对象的排序算法<br>
	 * 注：子类中如果要用到DOComparator来排序，那么一定要重写(Override)此方法 <br>
	 * @param o1
	 * @param o2
	 * @return
	 * Create author: 王浩羽 <br>
	 * Create on:Jan 19, 2009  <br>
	 * Edit author:  <br>
	 * Edit on:    <br>
	 * Why:     <br>
	 */
	protected int compareDO(D o1, D o2){
		String clazz = getDClassType().getSimpleName();
		throw new RuntimeException("please implement  compareDO("+ clazz + " o1, "+ clazz +" o2) method first !");
	}
}
